package com.nacos.gateway.server.filter;

import com.auth0.jwt.exceptions.JWTVerificationException;
import com.nacos.common.utils.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpCookie;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
@Slf4j
public class TokenFilter implements GlobalFilter, Ordered {
    @Autowired
    JWTUtils jwtUtils;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //head的token，需要前端支持
        String headToken = exchange.getRequest().getHeaders().getFirst("Authorization");
        //cookie的token,后端可设置
        HttpCookie httpCookie = exchange.getRequest().getCookies().getFirst("Authorization");
        String cookieToken = httpCookie == null ? null : httpCookie.getValue();
        String token = headToken != null ? headToken : cookieToken;

        //需要校验token的请求
        if (pathIscheckToken(exchange.getRequest().getPath().value())) {
            // 如果Token不存在或无效，则返回401错误
            if (token == null || !isValidToken(token)) {
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(org.springframework.http.HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            } else {
                // 如果Token有效，继续过滤器链
                return chain.filter(exchange);
            }

        } else {
            //需要校验token的请求
            return chain.filter(exchange);
        }
    }


    /**
     * 检查token是否有效
     *
     * @param token
     * @return
     */
    private boolean isValidToken(String token) {
        try {
            jwtUtils.verify(token);
            log.info("token校验有效");
        } catch (JWTVerificationException e) {
            log.error("token校验失败{}", token);
            log.error("token校验失败", e);
            return false;
        }
        return true;
    }

    /**
     * 检查path是否需要校验token
     *
     * @param path
     * @return
     */
    private boolean pathIscheckToken(String path) {
        if ("/client/login".equals(path)) {
            return false;
        }
        return true;
    }

    @Override
    public int getOrder() {
        // 设置过滤器的执行顺序
        return -1;
    }
}